use std::sync::Arc;

use chrono::{TimeZone, Local};
use prisma_client_rust::{
    QueryError,
    raw,
    // WhereQuery
};
use serde::{Serialize, Deserialize};
use rspc::{Type};
// use uuid::Uuid;

use crate::prisma::{PrismaClient, opinion, opinion_programme_book};

pub struct OpinionManager {
}

#[derive(Deserialize, Serialize, Type)]
pub struct SlugData {
    slug: String,
}

#[derive(Clone, Serialize, Deserialize, Type, Debug)]
pub struct OpinionParams {
    pub slug: Option<String>,
    pub page: i32,
    pub description: Option<String>,
    pub content: Option<String>,
    pub state: Option<String>,
    pub book_state: Option<String>
}

#[derive(Clone, Serialize, Deserialize, Type, Debug)]
pub struct SaveProgrammeBookData {
    pub uuid: String,
    pub department: String,
    pub leader: String,
    pub user: String,
    pub completed_at: String,
    pub book_completed_at: String,
    pub is_rectification: String,
    pub proposal: String,
    pub measures: String,
    pub rectification_status: String,
    pub completion_remark: Option<String>,
    pub payment_found: String,
    pub other: Option<String>,
    pub other_organization: Option<String>,
    pub investigation: Option<String>,
    pub perfect: Option<String>,
    pub status: String,
    pub book_status: String
}

// #[derive(Deserialize, Serialize, Type)]
// pub struct OpinionSchema {
//     uuid: String,
//     slug: String,
//     description: Option<String>,
//     content: Option<String>,
//     remark: Option<String>,
//     created_at: String,
//     updated_at: Option<String>,
//     records: Vec<record::Data>,
//     programme_book: Option<opinion_programme_book::Data>
// }

impl OpinionManager {
    // pub async fn get(client: Arc<PrismaClient>, args: OpinionParams) -> Result<Vec<opinion::Data>, QueryError> {
    //     println!("{:?}", args);

    //     let mut query = client
    //         .opinion()
    //         .find_many(vec![
    //             opinion::description::contains(args.description.unwrap().to_string()),
    //             opinion::content::contains(args.content.unwrap().to_string())
    //         ]);

    //     if !args.slug.is_none() {
    //         query
    //             .add_where(opinion::slug::equals(args.slug.unwrap().to_string()));
    //     }

    //     // let skip = (args.page - 1) * 20;

    //     let results = query
    //         // .skip(skip.into())
    //         // .take(20)
    //         // .include(opinion::include!({ records programme_book }))
    //         .exec()
    //         .await?;


    //     return Ok(
    //         results
    //     );
    // }

    pub async fn slugs(client: Arc<PrismaClient>) -> Result<Vec<SlugData>, QueryError> {
        return Ok(
            client
                ._query_raw(raw!(
                    "SELECT slug FROM opinions GROUP BY slug"
                ))
                .exec()
                .await?
        )
    }

    pub async fn update(client: Arc<PrismaClient>) -> Result<crate::prisma::opinion::Data, QueryError> {
        return Ok(
            client
                .opinion()
                .update(
                    opinion::uuid::equals("1".to_string()),
                    vec![opinion::slug::set("分类".to_string())]
                )
                .exec()
                .await?
        )
    }

    pub async fn create(client: Arc<PrismaClient>) -> Result<Vec<opinion::Data>, QueryError> {
        return Ok(
            client
                .opinion()
                .find_many(vec![])
                .exec()
                .await?
        );
    }

    pub async fn save_programme_book(client: Arc<PrismaClient>, args: SaveProgrammeBookData) -> Result<(), QueryError> {
        println!("{:?}", args);
        let uuid = args.uuid;
        println!("{:?}", uuid);

        let mut create = vec![
            opinion_programme_book::department::set(Some(args.department.to_string())),
            opinion_programme_book::leader::set(Some(args.leader.to_string())),
            opinion_programme_book::user::set(Some(args.user.to_string())),
            // opinion_programme_book::completed_at::set(Some(completed_at.unwrap().into())),
            // opinion_programme_book::book_completed_at::set(Some(book_completed_at.unwrap().into())),
            opinion_programme_book::is_rectification::set(Some(args.is_rectification.clone().into())),
            opinion_programme_book::proposal::set(Some(args.proposal.to_string())),
            opinion_programme_book::measures::set(Some(args.measures.to_string())),
            opinion_programme_book::rectification_status::set(Some(args.rectification_status.clone().into())),
            opinion_programme_book::completion_remark::set(Some(args.completion_remark.clone().unwrap().to_string())),
            opinion_programme_book::payment_found::set(args.payment_found.clone().into()),
            opinion_programme_book::other::set(Some(args.other.clone().unwrap().to_string())),
            opinion_programme_book::other_organization::set(Some(args.other_organization.clone().unwrap().to_string())),
            opinion_programme_book::investigation::set(Some(args.investigation.clone().unwrap().to_string())),
            opinion_programme_book::perfect::set(Some(args.perfect.clone().unwrap().to_string())),
            opinion_programme_book::status::set(args.status.clone().into()),
            opinion_programme_book::book_status::set(args.book_status.clone().into()),
            opinion_programme_book::created_at::set(Local::now().into()),
        ];

        let mut update = vec![
            opinion_programme_book::department::set(Some(args.department.to_string())),
            opinion_programme_book::leader::set(Some(args.leader.to_string())),
            opinion_programme_book::user::set(Some(args.user.to_string())),
            opinion_programme_book::is_rectification::set(Some(args.is_rectification.clone().into())),
            opinion_programme_book::proposal::set(Some(args.proposal.to_string())),
            opinion_programme_book::measures::set(Some(args.measures.to_string())),
            opinion_programme_book::rectification_status::set(Some(args.rectification_status.clone().into())),
            opinion_programme_book::completion_remark::set(Some(args.completion_remark.clone().unwrap().to_string())),
            opinion_programme_book::payment_found::set(args.payment_found.clone().into()),
            opinion_programme_book::other::set(Some(args.other.clone().unwrap().to_string())),
            opinion_programme_book::other_organization::set(Some(args.other_organization.clone().unwrap().to_string())),
            opinion_programme_book::investigation::set(Some(args.investigation.clone().unwrap().to_string())),
            opinion_programme_book::perfect::set(Some(args.perfect.clone().unwrap().to_string())),
            opinion_programme_book::status::set(args.status.clone().into()),
            opinion_programme_book::book_status::set(args.book_status.clone().into()),
            opinion_programme_book::updated_at::set(Some(Local::now().into()))
        ];

        // let completed_at = Local.datetime_from_str(&args.completed_at, "%Y-%m-%d %H:%M:%S");
        // println!("{:?}", completed_at.unwrap());
        // let book_completed_at = Local.datetime_from_str(&args.book_completed_at, "%Y-%m-%d %H:%M:%S");

        if !args.completed_at.is_empty() {
            let completed_at = Local.datetime_from_str(&args.completed_at, "%Y-%m-%d %H:%M:%S");
            create.push(opinion_programme_book::completed_at::set(Some(completed_at.unwrap().into())));
            update.push(opinion_programme_book::completed_at::set(Some(completed_at.unwrap().into())));
        }

        if !args.book_completed_at.is_empty() {
            let book_completed_at = Local.datetime_from_str(&args.book_completed_at, "%Y-%m-%d %H:%M:%S");
            create.push(opinion_programme_book::book_completed_at::set(Some(book_completed_at.unwrap().into())));
            update.push(opinion_programme_book::book_completed_at::set(Some(book_completed_at.unwrap().into())))
        }


        let _ = client
        .opinion_programme_book()
        .upsert(
            opinion_programme_book::uuid::equals(uuid.clone().to_string()),
            // uuid, slug, started_at, presenter, r#type, members, mut _params
            (
                opinion::UniqueWhereParam::UuidEquals(uuid.to_string()),
                create
            ),
            update
        )
        .exec()
        .await;

        return Ok(());
    }
}
